#!usr/bin/python
from __future__ import division

import sys
sys.setrecursionlimit(50)

import os.path
import random

import pygame
pygame.init()

keys_down = {
	pygame.K_UP: False,
	pygame.K_DOWN: False,
	pygame.K_LEFT: False,
	pygame.K_RIGHT: False,
}

key_delay = {
	pygame.K_UP: False,
	pygame.K_DOWN: False,
	pygame.K_LEFT: False,
	pygame.K_RIGHT: False,
}

from locals import *
import maps
import objects

class Game(object):
	def __init__(self):
		self.window = pygame.display.set_mode((512, 352)) 
		pygame.display.set_caption("pychallenge") 
		self.screen = pygame.display.get_surface()
		
		objects.load_graphics(OBJECT_DIR)
		objects.convert_graphics()
		
		self.viewport = (4 * 32, 3 * 32, 9 * 32, 9 * 32)

		self.level = 1
		self._restart_map()
		
		self.font = pygame.font.Font(os.path.join(MOD_DATA_DIR, "font.ttf"), 8)
	
	def _change_map(self, map):
		self.map = map
		
		self.events = []
		for key in keys_down:
			keys_down[key] = False
		
		for object in self.map.objects:
			if object.__class__.__name__ == "Player":
				self.player = object
				break
	
	def _restart_map(self):
		name = LEVELSET_LEVELS[self.level - 1]
		
		path = os.path.join(LEVELSET_DIR, name)
		self._change_map(maps.Map.load_map(open(path, 'r')))
		#maps.Map.save_map(self.map, open("maps/"+str(self.level)+"a.pcl", 'w'))
	
	def _next_map(self):
		self.level += 1
		
		try:
			self._restart_map()
		except IndexError:
			self.level = 1
			self._restart_map()
	
	def update(self):		
		self.map.update()
			
		if self.player.dead:
			self._restart_map()
		elif self.map.completed:
			self._next_map()
			
		if self.events and self.player.distance == 0:
			self.event(self.events.pop(0))
		
		if not self.player.moving and self.check_controls():
			movement = self.check_controls()
			
			move_x, move_y = movement
			
			if self.player.frozen[0]:
				move_x = 0
			if self.player.frozen[1]:
				move_y = 0
				
			movement = move_x, move_y
				
			if any(movement):
				self.player.move(movement, self.player.walk_speed)
				
		for key in key_delay:
			key_delay[key] = False
				
	def draw(self):		
		self.screen.fill((0, 0, 0))
		
		map_surface = self.screen.subsurface((32, 32, 288, 288))
		status_surface = self.screen.subsurface((352, 32, 128, 288))
		
		self._centre_viewport()
		self.map.draw(map_surface, self.viewport)
		
		# Level details:
		status_surface.blit(self.font.render("Level: %d" % self.level, False, (255, 255, 255)), (0, 0))
		status_surface.blit(self.font.render(self.map.name, False, (255, 255, 255)), (0, 16))
		status_surface.blit(self.font.render("By %s" % self.map.author, False, (255, 255, 255)), (0, 32))
		
		# List of player items:
		items = sorted(list(set(self.player.items)), key=lambda x: self.player.items.count(x), reverse=True)
		
		for index, item in enumerate(items):
			y = (index + 4) * 16
			
			status_surface.blit(self.font.render(item, False, (255, 255, 255)), (0, y))
			status_surface.blit(self.font.render(str(self.player.items.count(item)), False, (255, 255, 255)), (104, y))
		
		pygame.display.flip()

	def event(self, event):
		if event.type == pygame.KEYDOWN or event.type == pygame.KEYUP:			
			if event.key in key_delay and not key_delay[event.key]:
				key_delay[event.key] = (event.type == pygame.KEYDOWN)
				
			keys_down[event.key] = (event.type == pygame.KEYDOWN)
			
		if event.type == pygame.KEYDOWN and event.key == pygame.K_n:
			self._next_map()
	
	def check_controls(self):
		if keys_down[pygame.K_UP] or key_delay[pygame.K_UP]:
			return (0, -1)
		elif keys_down[pygame.K_DOWN] or key_delay[pygame.K_DOWN]:
			return (0, 1)
		elif keys_down[pygame.K_LEFT] or key_delay[pygame.K_LEFT]:
			return (-1, 0)
		elif keys_down[pygame.K_RIGHT] or key_delay[pygame.K_RIGHT]:
			return (1, 0)
		
	def _centre_viewport(self):
		x, y = self.player._draw_position()
		width, height = self.map.size
				
		view_x, view_y = x - (4 * 32), y - (4 * 32)
		
		view_x = clamp(0, view_x, (width * 32) - (9 * 32))
		view_y = clamp(0, view_y, (height * 32) - (9 * 32))
		
		self.viewport = (view_x, view_y, 9 * 32, 9 * 32)

def main():
	GAME = Game()
	
	quit = False
	clock = pygame.time.Clock()
	
	while not quit:
		clock.tick(50)
		pygame.time.wait(10)
		
		for event in pygame.event.get():
			if event.type == pygame.QUIT: 
				quit = True
				
			GAME.events.append(event)
		
		GAME.update()
		GAME.draw()

main()
#import profile
#profile.run('main()', 'prof.txt')